﻿#include "mode3_gamepad.hpp"
#include "mode_data.hpp"
#include "../../liblive2d/include/catlive2d.hpp"
#include "../../libcat/include/cat-window.hpp"
#include "../../libcat/include/cat-hook.hpp"
#include "../../libcat/include/util/jsoncpp.cpp"
#include "../../libcat/include/cat-audio.hpp"
namespace{
	gamepad * s_instance = NULL;

	POINT point;

	std::tuple<double, double> bezier(double ratio, std::vector<double>& points, int length)
	{
		double fact[22] = { 0.001, 0.001, 0.002, 0.006, 0.024, 0.12, 0.72, 5.04, 40.32, 362.88, 3628.8, 39916.8, 479001.6, 6227020.8, 87178291.2, 1307674368.0, 20922789888.0, 355687428096.0, 6402373705728.0, 121645100408832.0, 2432902008176640.0, 51090942171709440.0 };
		int nn = (length / 2) - 1;
		double xx = 0;
		double yy = 0;

		for (int point = 0; point <= nn; point++)
		{
			double tmp = fact[nn] / (fact[point] * fact[nn - point]) * pow(ratio, point) * pow(1 - ratio, nn - point);
			xx += points[2 * point] * tmp;
			yy += points[2 * point + 1] * tmp;
		}
		return std::make_tuple(xx / 1000, yy / 1000);
	}
	std::tuple<double, double> bezier2(double ratio, std::vector<double>& points, int length)
	{
		double fact[22] = { 0.001, 0.001, 0.002, 0.006, 0.024, 0.12, 0.72, 5.04, 40.32, 362.88, 3628.8, 39916.8, 479001.6, 6227020.8, 87178291.2, 1307674368.0, 20922789888.0, 355687428096.0, 6402373705728.0, 121645100408832.0, 2432902008176640.0, 51090942171709440.0 };
		int nn = (length / 2) - 1;
		double xx = 0;
		double yy = 0;

		for (int point = 0; point <= nn; point++)
		{
			double tmp = fact[nn] / (fact[point] * fact[nn - point]) * pow(ratio, point) * pow(1 - ratio, nn - point);
			xx += points[2 * point] * tmp;
			yy += points[2 * point + 1] * tmp;
		}
		return std::make_tuple(xx / 1000, yy / 1000);
	}
	static void sethand(double x, double y, double* pmpos0, double* pmpos1, std::vector<double>* ppss2, double dx, double dy)
	{
		// initializing pss and pss2 (kuvster's magic)
		int oof = 6;
		std::vector<double> pss = { 211.0, 159.0 };
		double dist = hypot(211 - x, 159 - y);
		double centreleft0 = 211 - 0.7237 * dist / 2;
		double centreleft1 = 159 + 0.69 * dist / 2;
		for (double i = 1; i < oof; i++)
		{
			double p0;
			double p1;
			std::vector<double> bez = { 211, 159, centreleft0, centreleft1, x, y };
			std::tie(p0, p1) = bezier(i / oof, bez, 6);
			pss.push_back(p0);
			pss.push_back(p1);
		}
		pss.push_back(x);
		pss.push_back(y);
		double a = y - centreleft1;
		double b = centreleft0 - x;
		double le = hypot(a, b);
		a = x + a / le * 60;
		b = y + b / le * 60;
		int a1 = 258;
		int a2 = 228;
		dist = hypot(a1 - a, a2 - b);
		double centreright0 = a1 - 0.6 * dist / 2;
		double centreright1 = a2 + 0.8 * dist / 2;
		int push = 20;
		double s = x - centreleft0;
		double t = y - centreleft1;
		le = hypot(s, t);
		s *= push / le;
		t *= push / le;
		double s2 = a - centreright0;
		double t2 = b - centreright1;
		le = hypot(s2, t2);
		s2 *= push / le;
		t2 *= push / le;
		for (double i = 1; i < oof; i++)
		{
			double p0;
			double p1;
			std::vector<double> bez = { x, y, x + s, y + t, a + s2, b + t2, a, b };
			std::tie(p0, p1) = bezier(i / oof, bez, 8);
			pss.push_back(p0);
			pss.push_back(p1);
		}
		pss.push_back(a);
		pss.push_back(b);
		for (double i = oof - 1; i > 0; i--)
		{
			double p0;
			double p1;
			std::vector<double> bez = { 1.0 * a1, 1.0 * a2, centreright0, centreright1, a, b };
			std::tie(p0, p1) = bezier(i / oof, bez, 6);
			pss.push_back(p0);
			pss.push_back(p1);
		}
		pss.push_back(a1);
		pss.push_back(a2);
		*pmpos0 = (a + x) / 2 - 52 - 15;
		*pmpos1 = (b + y) / 2 - 34 + 5;


		const int iter = 25;

		*ppss2 = { pss[0] + dx, pss[1] + dy };
		for (double i = 1; i < iter; i++)
		{
			double p0;
			double p1;
			std::tie(p0, p1) = bezier(i / iter, pss, 38);
			ppss2->push_back(p0 + dx);
			ppss2->push_back(p1 + dy);
		}
		ppss2->push_back(pss[36] + dx);
		ppss2->push_back(pss[37] + dy);
	}

	static void sethand2(double x, double y, double* pmpos0, double* pmpos1, std::vector<double>* ppss2, double dx, double dy)
	{
		// initializing pss and pss2 (kuvster's magic)
		int oof = 6;
		std::vector<double> pss = { 211.0, 159.0 };
		double dist = hypot(211 - x, 159 - y);
		double centreleft0 = 211 + 0.3 * dist / 2;
		double centreleft1 = 159 + 0.69 * dist / 2;
		for (double i = 1; i < oof; i++)
		{
			double p0;
			double p1;
			std::vector<double> bez = { 211, 159, centreleft0, centreleft1, x, y };
			std::tie(p0, p1) = bezier2(i / oof, bez, 6);
			pss.push_back(p0);
			pss.push_back(p1);
		}
		pss.push_back(x);
		pss.push_back(y);
		double a = y - centreleft1;
		double b = centreleft0 - x;
		double le = hypot(a, b);
		a = x + a / le * 60;
		b = y + b / le * 60;
		int a1 = 298;
		int a2 = 159;
		dist = hypot(a1 - a, a2 - b);
		double centreright0 = a1 - 0.6 * dist / 2;
		double centreright1 = a2 + 0.8 * dist / 2;
		int push = 20;
		double s = x - centreleft0;
		double t = y - centreleft1;
		le = hypot(s, t);
		s *= push / le;
		t *= push / le;
		double s2 = a - centreright0;
		double t2 = b - centreright1;
		le = hypot(s2, t2);
		s2 *= push / le;
		t2 *= push / le;
		for (double i = 1; i < oof; i++)
		{
			double p0;
			double p1;
			std::vector<double> bez = { x, y, x + s, y + t, a + s2, b + t2, a, b };
			std::tie(p0, p1) = bezier2(i / oof, bez, 8);
			pss.push_back(p0);
			pss.push_back(p1);
		}
		pss.push_back(a);
		pss.push_back(b);
		for (double i = oof - 1; i > 0; i--)
		{
			double p0;
			double p1;
			std::vector<double> bez = { 1.0 * a1, 1.0 * a2, centreright0+40, centreright1+40, a, b };
			std::tie(p0, p1) = bezier2(i / oof, bez, 6);
			pss.push_back(p0);
			pss.push_back(p1);
		}
		pss.push_back(a1);
		pss.push_back(a2);
		*pmpos0 = (a + x) / 2 - 52 - 15;
		*pmpos1 = (b + y) / 2 - 34 + 5;


		const int iter = 25;

		*ppss2 = { pss[0] + dx, pss[1] + dy };
		for (double i = 1; i < iter; i++)
		{
			double p0;
			double p1;
			std::tie(p0, p1) = bezier2(i / iter, pss, 38);
			ppss2->push_back(p0 + dx);
			ppss2->push_back(p1 + dy);
		}
		ppss2->push_back(pss[36] + dx);
		ppss2->push_back(pss[37] + dy);
	}

	static bool checkDist(float a,float b,float value) {
		float res = a*a + b*b;
		if (res > value)
			return true;
		else 
			return false;
	}
}

gamepad* gamepad::GetInstance()
{
	if (s_instance == NULL)
	{
		s_instance = new gamepad();
	}
	return s_instance;
}

void gamepad::ReleaseInstance()
{
	if (s_instance != NULL)
	{
		delete s_instance;
	}
	s_instance = NULL;
}

void gamepad::Init(Json::Value cfg)
{

	renderWindowWidth = cfg["decoration"]["window_size"][0].asInt();
	renderWindowHeight = cfg["decoration"]["window_size"][1].asInt();
	cat_set_gui_size(renderWindowWidth, renderWindowHeight);

	std::string gamepad_module_path;
	for (auto entry = cfg["plugins"]["mode_ex"].begin(); entry != cfg["plugins"]["mode_ex"].end(); entry++)
	{
		if ((*entry)["module_id"].asInt() == 3) {
			gamepad_module_path = (*entry)["module_data_path"].asCString();
			break;
		}
	}

	const char* data = ModeData::LoadFileAsBytes(gamepad_module_path.c_str());
	if (data == NULL)
	{
		isInit = false;
		return;
	}
	JSONCPP_STRING error;
	Json::CharReaderBuilder json_builder;
	Json::Value root;
	Json::CharReader* json_reader = json_builder.newCharReader();
	bool parsingSuccessful = json_reader->parse(data, data + strlen(data), &root, &error);

	if (!parsingSuccessful) {
		return;
	}
	delete json_reader;
	delete data;

	key_clock.restart();

	std::string mode_path = gamepad_module_path.substr(0, gamepad_module_path.find_last_of("/") + 1);
	if (mode_path.size() == 0) {
		mode_path = gamepad_module_path.substr(0, gamepad_module_path.find_last_of("\\") + 1);
	}

	bg.setTexture(ModeData::load_texture2(mode_path + "bg.png"));
	cat.setTexture(ModeData::load_texture2(mode_path + "cat.png"));
	left_up.setTexture(ModeData::load_texture2(mode_path + "lefthand/leftup.png"));
	right_up.setTexture(ModeData::load_texture2(mode_path + "righthand/rightup.png"));
	l2.setTexture(ModeData::load_texture2(mode_path + "l2.png"));
	r2.setTexture(ModeData::load_texture2(mode_path + "r2.png"));
	l2.setColor(sf::Color(255, 255, 255, 0));
	r2.setColor(sf::Color(255, 255, 255, 0));
	l2_hand.setTexture(ModeData::load_texture2(mode_path + "l2_hand.png"));
	r2_hand.setTexture(ModeData::load_texture2(mode_path + "r2_hand.png"));
	left_stick.setTexture(ModeData::load_texture2(mode_path + "l3.png"));
	left_stick_down.setTexture(ModeData::load_texture2(mode_path + "l3_down.png"));
	right_stick.setTexture(ModeData::load_texture2(mode_path + "r3.png"));
	right_stick_down.setTexture(ModeData::load_texture2(mode_path + "r3_down.png"));

	leftHandTex.loadFromFile(mode_path + "arm_L.png");
	rightHandTex.loadFromFile(mode_path + "arm_R.png");

	int index = 0;
	while (!root["gamepad"]["lefthand"][index].isNull()) {
		std::string imgpath = mode_path + "/lefthand/" + std::to_string(index) + ".png";
		int key_index = 0;
		while (!root["gamepad"]["lefthand"][index][key_index].isNull()) {
			int keycode = root["gamepad"]["lefthand"][index][key_index].asInt();
			left_hands_down[imgpath].keys.push_back(keycode);
			joy_states[keycode] = false;
			key_index++;
		}
		ModeData::load_texture2(imgpath);
		index++;
	}

	index = 0;
	while (!root["gamepad"]["righthand"][index].isNull()) {
		std::string imgpath = mode_path + "/righthand/" + std::to_string(index) + ".png";
		int key_index = 0;
		while (!root["gamepad"]["righthand"][index][key_index].isNull()) {
			int keycode = root["gamepad"]["righthand"][index][key_index].asInt();
			right_hands_down[imgpath].keys.push_back(keycode);
			joy_states[keycode] = false;
			key_index++;
		}
		ModeData::load_texture2(imgpath);
		index++;
	}

	index = 0;
	while (!root["gamepad"]["keyboard"][index].isNull()) {
		std::string imgpath = mode_path + "keyboard/" + std::to_string(index) + ".png";
		int key_index = 0;
		while (!root["gamepad"]["keyboard"][index][key_index].isNull()) {
			int keycode = root["gamepad"]["keyboard"][index][key_index].asInt();
			keys[imgpath].keys.push_back(keycode);
			joy_states[keycode] = false;
			key_index++;
		}
		ModeData::load_texture2(imgpath);
		index++;
	}
	index = 0;
	while (!root["gamepad"]["face"][index].isNull()) {
		std::string imgpath = mode_path + "face/" + std::to_string(index) + ".png";
		int key_index = 0;
		while (!root["gamepad"]["face"][index][key_index].isNull()) {
			int keycode = root["gamepad"]["face"][index][key_index].asInt();
			faces[imgpath].keys.push_back(keycode);
			states[keycode] = false;
			key_index++;
		}
		ModeData::load_texture2(imgpath);
		index++;
	}

	index = 0;
	while (!root["gamepad"]["sounds"][index].isNull()) {
		std::string imgpath = mode_path + "sounds/" + std::to_string(index) + ".flac";
		int key_index = 0;
		while (!root["gamepad"]["sounds"][index][key_index].isNull()) {
			int keycode = root["gamepad"]["sounds"][index][key_index].asInt();
			sounds[imgpath].keys.push_back(keycode);
			states[keycode] = false;
			key_index++;
		}
		index++;
	}

	index = 0;
	while (!root["gamepad"]["l2d_motion"][index].isNull()) {
		std::string imgpath = std::to_string(index);
		int key_index = 0;
		while (!root["gamepad"]["l2d_motion"][index][key_index].isNull()) {
			int keycode = root["gamepad"]["l2d_motion"][index][key_index].asInt();
			motions[imgpath].keys.push_back(keycode);
			states[keycode] = false;
			key_index++;
		}
		index++;
	}

	index = 0;
	while (!root["gamepad"]["l2d_expression"][index].isNull()) {
		std::string imgpath = std::to_string(index);
		int key_index = 0;
		while (!root["gamepad"]["l2d_expression"][index][key_index].isNull()) {
			int keycode = root["gamepad"]["l2d_expression"][index][key_index].asInt();
			expression[imgpath].keys.push_back(keycode);
			states[keycode] = false;
			key_index++;
		}
		index++;
	}

	axis["L3"].keys.push_back(root["gamepad"]["L3"][0].asInt());
	axis["L3"].keys.push_back(root["gamepad"]["L3"][1].asInt());
	

	axis["R3"].keys.push_back(root["gamepad"]["R3"][0].asInt());
	axis["R3"].keys.push_back(root["gamepad"]["R3"][1].asInt());
	

	axis["L2"].keys.push_back(root["gamepad"]["L2"][0].asInt());
	axis["R2"].keys.push_back(root["gamepad"]["R2"][0].asInt());
	
	axis_states[root["gamepad"]["L3"][0].asInt()].value = 0.0f;
	axis_states[root["gamepad"]["L3"][1].asInt()].value = 0.0f;
	axis_states[root["gamepad"]["R3"][0].asInt()].value = 0.0f;
	axis_states[root["gamepad"]["R3"][1].asInt()].value = 0.0f;
	axis_states[root["gamepad"]["L2"][0].asInt()].value = -1.0f;
	axis_states[root["gamepad"]["R2"][0].asInt()].value = -1.0f;

	joy_states[root["gamepad"]["L3_down"][0].asInt()] = false;
	joy_states[root["gamepad"]["R3_down"][0].asInt()] = false;
	axiskeys["L3_down"].keys.push_back(root["gamepad"]["L3_down"][0].asInt());
	axiskeys["R3_down"].keys.push_back(root["gamepad"]["R3_down"][0].asInt());

	std::string l2dmodelPath = mode_path + "cat_model/";
	cat_live2d_load_model(l2dmodelPath.c_str(), "cat.model3.json");

	l3_flage = false;
	r3_flage = false;
	l2_flage = false;
	r2_flage = false;

	isInit = true;

	Update(cfg);
}

void gamepad::Update(Json::Value cfg)
{
	renderWindowWidth = cfg["decoration"]["window_size"][0].asInt();
	renderWindowHeight = cfg["decoration"]["window_size"][1].asInt();

	renderTexture.create(renderWindowWidth, renderWindowHeight, false);
	renderTexture.setSmooth(true);
	renderSprite.setTexture(renderTexture.getTexture());
	renderSprite.setTextureRect(sf::IntRect(sf::Vector2i(0, 0), sf::Vector2i(renderTexture.getSize().x, renderTexture.getSize().y)));

	red_value = cfg["decoration"]["armLineColor"][0].asInt();
	green_value = cfg["decoration"]["armLineColor"][1].asInt();
	blue_value = cfg["decoration"]["armLineColor"][2].asInt();

	motion_keep = cfg["main_decoration"]["motion_keep"].asBool();
	sound_keep = cfg["main_decoration"]["sound_keep"].asBool();

	gamePadId = cfg["main_decoration"]["gamepad_ID"].asInt();

	cat_hook_switch_target(gamePadId);

	isLive2d = cfg["main_decoration"]["l2d"].asBool();
	if (isLive2d) {
		l2d_correct = cfg["decoration"]["l2d_correct"].asFloat();
		l2d_offset_x = cfg["decoration"]["l2d_offset"][0].asFloat();
		l2d_offset_y = cfg["decoration"]["l2d_offset"][1].asFloat();
		float speed = cfg["main_decoration"]["l2d_spead"].asFloat();
		l2d_random_motion = cfg["main_decoration"]["l2d_random_motion"].asBool();
		l2d_random_expression = cfg["main_decoration"]["l2d_random_expression"].asBool();
		cat_live2d_translate(l2d_offset_x, l2d_offset_y);
		cat_live2d_scale(l2d_correct, l2d_correct);
		cat_live2d_speed(speed);
		cat_live2d_set_random_motion(l2d_random_motion, l2d_random_expression);
		cat_live2d_resize(renderWindowWidth, renderWindowHeight);
	}

	cat_audio_set_silent(cfg["main_decoration"]["silent"].asBool());
}

void gamepad::OnJoyButtonPress(const cat_joystick_button_event* event, bool up)
{blog(LOG_DEBUG, "key %d", event->native_vkey);
	if (joy_states.find(event->native_vkey) != joy_states.end()) {
		joy_states[event->native_vkey] = !up;
		
	}
}

void gamepad::OnJoyAxisMove(const cat_joystick_axis_move_event* event)
{
	if (axis_states.find(event->axisid) != axis_states.end()) {
		float axis_v= static_cast<float>(event->value)/ 32768.0f;
		axis_v <0.1 && axis_v >-0.1?axis_states[event->axisid].value = 0.0f:axis_states[event->axisid].value = axis_v;		
	}

	if (isLive2d) {
		int lx, ly,rx,ry;
		lx = axis["L3"].keys[0];
		ly = axis["L3"].keys[1];
		rx = axis["R3"].keys[0];
		ry = axis["R3"].keys[1];
		if (checkDist(axis_states[lx].value, axis_states[ly].value, 0.02)) {
			if (checkDist(axis_states[lx].value, axis_states[ly].value, 0.04)) {
				l3_flage = true;
				//cat_live2d_on_left_hand_down_callback(false);
				cat_live2d_joy_on_show_left_hand_callback(false);
			}
			cat_live2d_joy_on_l_stick_move_callback(axis_states[lx].value, -axis_states[ly].value);
		}
		else {
			l3_flage = false;
			//cat_live2d_on_left_hand_down_callback(true);
			cat_live2d_joy_on_show_left_hand_callback(true);
			cat_live2d_joy_on_l_stick_move_callback(0, 0);
		}
		if (checkDist(axis_states[rx].value, axis_states[ry].value, 0.02)) {
			if (checkDist(axis_states[rx].value, axis_states[ry].value, 0.04)) {
				r3_flage = true;
				//cat_live2d_on_right_hand_down_callback(false);
				cat_live2d_joy_on_show_right_hand_callback(false);
			}
			cat_live2d_joy_on_r_stick_move_callback(axis_states[rx].value, -axis_states[ry].value);
		}
		else {
			r3_flage = false;
			//cat_live2d_on_right_hand_down_callback(true);
			cat_live2d_joy_on_show_right_hand_callback(true);
			cat_live2d_joy_on_r_stick_move_callback(0, 0);
		}
	}

	int ml2, mr2;
	ml2 = axis["L2"].keys[0];
	mr2 = axis["R2"].keys[0];
	l2.setColor(sf::Color(255, 255, 255, 255 * (axis_states[ml2].value + 1) / 2));
	r2.setColor(sf::Color(255, 255, 255, 255 * (axis_states[mr2].value + 1) / 2));
	if (axis_states[ml2].value > 0&&!l3_flage)
	{
		if (isLive2d)
		l3_flage = true;
		l2_flage = true;
	}else
		l2_flage = false;

	if (axis_states[mr2].value > 0&&!r3_flage)
	{
		if (isLive2d)
		r3_flage = true;
		r2_flage = true;
	}else
		r2_flage = false;
}

void gamepad::OnKeyPress(const cat_key_event* event, bool key_up)
{
	if (states.find(event->native_vkey) != states.end()) {
		states[event->native_vkey] = !key_up;
	}
}


void gamepad::Draw(void* _window)
{
	cat_window* window = (cat_window*)_window;
	if (isInit) {
		renderTexture.clear(sf::Color(0, 0, 0, 0));
		if (isLive2d) {	
			renderTexture.draw(bg);
			drawKey(renderTexture);				
			drawAxis(renderTexture);
			cat_live2d_run(NULL);	
			playMotion();
			playExpression();	
		}
		else 
		{	
			renderTexture.draw(cat);
			renderTexture.draw(bg);
			drawKey(renderTexture);
			drawAxis(renderTexture);
			drawCat(renderTexture); 
			
		}
		drawFace(renderTexture);
		drawLeftHand(renderTexture);
		drawRightHand(renderTexture);
		playSound();

		renderTexture.display();
		window->window->draw(renderSprite);		
	}

}

void gamepad::Release()
{
	ModeData::clear_holder();
	isInit = false;
	states.clear();

	joy_states.clear();
	axis_states.clear();
	axis.clear();

	left_hands_down.clear();
	right_hands_down.clear();
	keys.clear();
	axiskeys.clear();
	faces.clear();
	sounds.clear();
	motions.clear();
	expression.clear();
}

gamepad::gamepad():
	isInit(false),
	gamePadId(0)
{
	
}

gamepad::~gamepad()
{
	
}

void gamepad::drawCat(sf::RenderTexture& _window)
{
	int rx, ry;
	rx = axis["R3"].keys[0];
	ry = axis["R3"].keys[1];
	
	//_window.draw(cat);
	{
		double fx, fy;
		fx = axis_states[rx].value/8;
		fy = axis_states[ry].value/5;
		double x = -97 * fx + 44 * fy + 100;
		double y = -76 * fx - 40 * fy + 252;

		double mpos0, mpos1;
		double dx = -38;
		double dy = -50;
		std::vector<double>pss2;
		//计算右手的贝塞尔曲线数组
		sethand(x, y, &mpos0, &mpos1, &pss2, dx, dy);

		//对右手进行位置处理
		/*
		for (int i = 0; i < 26; i++)
		{
			pss2[i * 2] += hand_offset_x;
			pss2[i * 2 + 1] += hand_offset_y;
		}*/
		right_stick.setPosition(x + dx-15, y + dy+15);
		right_stick_down.setPosition(x + dx-15, y + dy+15);
		_window.draw(right_stick);
		if(r3_down_flag)
			_window.draw(right_stick_down);

		if (checkDist(axis_states[rx].value, axis_states[ry].value, 0.02)) {
		sf::ConvexShape fill(26);
		for (int i = 0; i < 26; i++)
		{
			fill.setPoint(i, sf::Vector2f(pss2[i * 2], pss2[i * 2 + 1]));
		}
		fill.setTexture(&rightHandTex);
		_window.draw(fill);

		drawline(_window, pss2, red_value, green_value, blue_value);
		r3_flage = true;
		}
		else {
			r3_flage = false;
		}
	}

	int lx, ly;
	lx = axis["L3"].keys[0];
	ly = axis["L3"].keys[1]; 
	{
		double fx, fy;
		fx = axis_states[lx].value / 10;
		fy = axis_states[ly].value / 7;
		double x = -97 * fx + 44 * fy + 220;
		double y = -76 * fx - 40 * fy + 240;

		double mpos0, mpos1;
		double dx = 178;
		double dy = 50;
		std::vector<double>pss2;
		//计算右手的贝塞尔曲线数组
		sethand2(x, y, &mpos0, &mpos1, &pss2, dx, dy);

		//对右手进行位置处理
		left_stick.setPosition(x + dx+10 , y + dy-10 );
		left_stick_down.setPosition(x + dx+10 , y + dy-10 );
		_window.draw(left_stick);
		if (l3_down_flag)
			_window.draw(left_stick_down);
		
		/*for (int i = 0; i < 26; i++)
		{
			pss2[i * 2] +=300;
			pss2[i * 2 + 1] += 20;
		}*/
		
		if (checkDist(axis_states[lx].value, axis_states[ly].value, 0.02)) {
			sf::ConvexShape fill(26);
			for (int i = 0; i < 26; i++)
			{
				fill.setPoint(i, sf::Vector2f(pss2[i * 2], pss2[i * 2 + 1]));
			}
			fill.setTexture(&rightHandTex);
			//fill.scale(-1.f, 1.f);
			_window.draw(fill);

			drawline(_window, pss2, red_value, green_value, blue_value);
			l3_flage = true;
		}
		else {
			l3_flage = false;
		}
	}

}

//根据数组绘制曲线
void gamepad::drawline(sf::RenderTexture& window, std::vector<double> pss2, int red_value, int green_value, int blue_value)
{
	// drawing first arm arc
	int shad = 77;
	sf::VertexArray edge(sf::TriangleStrip, 52);
	double width = 7;
	sf::CircleShape circ(width / 2);
	circ.setFillColor(sf::Color(red_value, green_value, blue_value, shad));
	circ.setPosition(pss2[0] - width / 2, pss2[1] - width / 2);

	window.draw(circ);
	for (int i = 0; i < 50; i += 2)
	{
		double vec0 = pss2[i] - pss2[i + 2];
		double vec1 = pss2[i + 1] - pss2[i + 3];
		double dist = hypot(vec0, vec1);
		edge[i].position = sf::Vector2f(pss2[i] + vec1 / dist * width / 2, pss2[i + 1] - vec0 / dist * width / 2);
		edge[i + 1].position = sf::Vector2f(pss2[i] - vec1 / dist * width / 2, pss2[i + 1] + vec0 / dist * width / 2);
		edge[i].color = sf::Color(0, 0, 0, shad);
		edge[i + 1].color = sf::Color(0, 0, 0, shad);
		width -= 0.08;
	}
	double vec0 = pss2[50] - pss2[48];
	double vec1 = pss2[51] - pss2[49];
	double dist = hypot(vec0, vec1);
	edge[51].position = sf::Vector2f(pss2[50] + vec1 / dist * width / 2, pss2[51] - vec0 / dist * width / 2);
	edge[50].position = sf::Vector2f(pss2[50] - vec1 / dist * width / 2, pss2[51] + vec0 / dist * width / 2);
	edge[50].color = sf::Color(red_value, green_value, blue_value, shad);
	edge[51].color = sf::Color(red_value, green_value, blue_value, shad);
	window.draw(edge);
	circ.setRadius(width / 2);
	circ.setPosition(pss2[50] - width / 2, pss2[51] - width / 2);
	window.draw(circ);

	// drawing second arm arc
	sf::VertexArray edge2(sf::TriangleStrip, 52);
	width = 6;
	sf::CircleShape circ2(width / 2);
	circ2.setFillColor(sf::Color(red_value, green_value, blue_value));
	circ2.setPosition(pss2[0] - width / 2, pss2[1] - width / 2);
	window.draw(circ2);
	for (int i = 0; i < 50; i += 2)
	{
		vec0 = pss2[i] - pss2[i + 2];
		vec1 = pss2[i + 1] - pss2[i + 3];
		double dist = hypot(vec0, vec1);
		edge2[i].position = sf::Vector2f(pss2[i] + vec1 / dist * width / 2, pss2[i + 1] - vec0 / dist * width / 2);
		edge2[i + 1].position = sf::Vector2f(pss2[i] - vec1 / dist * width / 2, pss2[i + 1] + vec0 / dist * width / 2);
		edge2[i].color = sf::Color(red_value, green_value, blue_value);
		edge2[i + 1].color = sf::Color(red_value, green_value, blue_value);
		width -= 0.08;
	}
	vec0 = pss2[50] - pss2[48];
	vec1 = pss2[51] - pss2[49];
	dist = hypot(vec0, vec1);
	edge2[51].position = sf::Vector2f(pss2[50] + vec1 / dist * width / 2, pss2[51] - vec0 / dist * width / 2);
	edge2[50].position = sf::Vector2f(pss2[50] - vec1 / dist * width / 2, pss2[51] + vec0 / dist * width / 2);
	edge2[50].color = sf::Color(red_value, green_value, blue_value);
	edge2[51].color = sf::Color(red_value, green_value, blue_value);
	window.draw(edge2);
	circ2.setRadius(width / 2);
	circ2.setPosition(pss2[50] - width / 2, pss2[51] - width / 2);
	window.draw(circ2);
}

void gamepad::drawKey(sf::RenderTexture& _window)
{
	for (auto entry = keys.begin(); entry != keys.end(); entry++) {
		bool flag = true;
		for (auto key_state = (*entry).second.keys.begin(); key_state != (*entry).second.keys.end(); key_state++)
		{
			flag &= joy_states[(*key_state)];
		}

		flag ? (*entry).second.isShow = true : (*entry).second.isShow = false;

		if ((*entry).second.isShow == true) {
			sf::Sprite key;
			key.setTexture(ModeData::load_texture2((*entry).first));
			_window.draw(key);
		}
	}
}

void gamepad::drawAxis(sf::RenderTexture& _window)
{
	for (auto entry = axiskeys.begin(); entry != axiskeys.end(); entry++) {
		bool flag = true;
		for (auto key_state = (*entry).second.keys.begin(); key_state != (*entry).second.keys.end(); key_state++)
		{
			flag &= joy_states[(*key_state)];
		}

		flag ? (*entry).second.isShow = true : (*entry).second.isShow = false;

		if ((*entry).second.isShow == true) {
			if (strcmp((*entry).first.c_str(), "L3_down")) 
			{
				cat_live2d_joy_on_left_stick_down_callback(false);
				l3_down_flag = true;
			}			
			if (strcmp((*entry).first.c_str(), "R3_down"))
			{
				cat_live2d_joy_on_right_stick_down_callback(false);
				r3_down_flag = true;
			}			
		}
		else {
			if (strcmp((*entry).first.c_str(), "L3_down"))
			{
				cat_live2d_joy_on_left_stick_down_callback(true);
				l3_down_flag = false;
			}
			if (strcmp((*entry).first.c_str(), "R3_down"))
			{
				cat_live2d_joy_on_right_stick_down_callback(true);
				r3_down_flag = false;
			}
		}
	}
	
	_window.draw(l2);
	_window.draw(r2);
}

void gamepad::drawLeftHand(sf::RenderTexture& _window)
{
	bool HandUp = true;
	std::string whichHand;
	for (auto entry = left_hands_down.begin(); entry != left_hands_down.end(); entry++) {
		
		bool flag = true;
		for (auto key_state = (*entry).second.keys.begin(); key_state != (*entry).second.keys.end(); key_state++)
		{
			flag &= joy_states[(*key_state)];
		}

		if (flag && !(*entry).second.isShow) {
			(*entry).second.record = key_clock.getElapsedTime();
		}

		flag ? (*entry).second.isShow = true : (*entry).second.isShow = false;

		if ((*entry).second.isShow)
		{
			if (whichHand.empty()) {
			whichHand = (*entry).first;
			}
			if (left_hands_down[whichHand].record < (*entry).second.record)
			{
				whichHand = (*entry).first;
			}
			HandUp = false;
		}
	}

	

	if (l2_flage) {
		cat_live2d_on_left_hand_down_callback(false);
		_window.draw(l2_hand);
	}
	else if(!l3_flage){
		cat_live2d_on_left_hand_down_callback(HandUp);

		if (!whichHand.empty()&&left_hands_down[whichHand].isShow) {
			sf::Sprite hand;
			hand.setTexture(ModeData::load_texture2(whichHand));
			_window.draw(hand);
		}
		if (!isLive2d && HandUp)
			_window.draw(left_up);
	}	
	else {
		cat_live2d_on_left_hand_down_callback(false);
	}
}

void gamepad::drawRightHand(sf::RenderTexture& _window)
{
	bool HandUp = true;
	bool flag;
	std::string whichHand;
	for (auto entry = right_hands_down.begin(); entry != right_hands_down.end(); entry++) {
	    flag = true;
		for (auto key_state = (*entry).second.keys.begin(); key_state != (*entry).second.keys.end(); key_state++)
		{
			flag &= joy_states[(*key_state)];
		}

		if (flag && !(*entry).second.isShow) {
			(*entry).second.record = key_clock.getElapsedTime();
		}

		flag ? (*entry).second.isShow = true : (*entry).second.isShow = false;

		if ((*entry).second.isShow)
		{
			if (whichHand.empty()) {
				whichHand = (*entry).first;
			}
			if (right_hands_down[whichHand].record <(*entry).second.record)
			{
				whichHand = (*entry).first;
			}
			HandUp = false;
		}
	}
	

	if (r2_flage) {
		cat_live2d_on_right_hand_down_callback(false);
		_window.draw(r2_hand);
	}
	else if (!r3_flage) {
		cat_live2d_on_right_hand_down_callback(HandUp );

		if (!whichHand.empty()&&right_hands_down[whichHand].isShow) {
			sf::Sprite hand;
			hand.setTexture(ModeData::load_texture2(whichHand));
			_window.draw(hand);
		}

		if (!isLive2d && HandUp)
			_window.draw(right_up);
	}
	else {
		cat_live2d_on_right_hand_down_callback(false);
	}

	
}

void gamepad::drawFace(sf::RenderTexture& _window)
{
	for (auto entry = faces.begin(); entry != faces.end(); entry++) {
		bool flag = true;
		for (auto key_state = (*entry).second.keys.begin(); key_state != (*entry).second.keys.end(); key_state++)
		{
			flag &= states[(*key_state)];
		}
		flag ? (*entry).second.isShow = true : (*entry).second.isShow = false;

		if (motion_keep) {
			if ((*entry).second.isShow != (*entry).second.isLastShow) {
				if ((*entry).second.isLastShow)
					(*entry).second.LastShowCount++;
				(*entry).second.isLastShow = (*entry).second.isShow;
			}

			if ((*entry).second.LastShowCount % 2) {
				sf::Sprite key;
				key.setTexture(ModeData::load_texture2((*entry).first));
				_window.draw(key);
			}
		}
		else if ((*entry).second.isShow) {
			sf::Sprite key;
			key.setTexture(ModeData::load_texture2((*entry).first));
			_window.draw(key);
		}
	}
}

void gamepad::playSound()
{
	for (auto entry = sounds.begin(); entry != sounds.end(); entry++) {
		bool flag = true;
		for (auto key_state = (*entry).second.keys.begin(); key_state != (*entry).second.keys.end(); key_state++)
		{
			flag &= states[(*key_state)];
		}

		flag ? (*entry).second.isShow = true : (*entry).second.isShow = false;

		if ((*entry).second.isShow != (*entry).second.isLastShow) {
			if (!(*entry).second.isLastShow)
				(*entry).second.LastShowCount++;
			(*entry).second.isLastShow = (*entry).second.isShow;
		}

		if ((*entry).second.LastShowCount % 2) {
			if ((*entry).second.isShow)
				cat_play_sound((*entry).first.c_str(), sound_keep);
			(*entry).second.LastShowCount++;
		}
	}
}

void gamepad::playMotion()
{
	for (auto entry = motions.begin(); entry != motions.end(); entry++) {
		bool flag = true;
		for (auto key_state = (*entry).second.keys.begin(); key_state != (*entry).second.keys.end(); key_state++)
		{
			flag &= states[(*key_state)];
		}
		if (flag == true) {
			cat_live2d_play_motion("CAT_motion", std::stoi((*entry).first));
		}
	}
}

void gamepad::playExpression()
{
	for (auto entry = expression.begin(); entry != expression.end(); entry++) {
		bool flag = true;
		for (auto key_state = (*entry).second.keys.begin(); key_state != (*entry).second.keys.end(); key_state++)
		{
			flag &= states[(*key_state)];
		}

		if (motion_keep) {
			if (flag != (*entry).second.isLastShow) {
				if (flag)
				{
					(*entry).second.LastShowCount++;
				}
				(*entry).second.isLastShow = flag;
			}

			if ((*entry).second.LastShowCount % 2) {
				if (flag && !(*entry).second.isShow)
				{
					for (auto entry2 = expression.begin(); entry2 != expression.end(); entry2++) {
						(*entry2).second.isShow = false;
					}
					(*entry).second.isShow = true;
					cat_live2d_set_expression_by_id(std::stoi((*entry).first));
				}
				else if (flag)
				{
					cat_live2d_set_expression_by_id(0);
					(*entry).second.isShow = false;
				}
				(*entry).second.LastShowCount++;
			}
		}
		else
		{
			if (flag) {
				cat_live2d_set_expression_by_id(std::stoi((*entry).first));
				(*entry).second.isShow = true;
			}
			else if ((*entry).second.isShow)
			{
				(*entry).second.isShow = false;
				cat_live2d_set_expression_by_id(0);
			}

		}
	}
}





